﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace OrderAggregator.InputFormats
{
    /// <summary>
    /// Базовый класс формата входных данных
    /// </summary>
    public abstract class BaseOrderFormat
    {
        /// <summary>
        /// .txt
        /// </summary>
        protected const string dotTXT = ".txt";

        /// <summary>
        /// .xls
        /// </summary>
        protected const string dotXLS = ".xls";

        /// <summary>
        /// .xlsx
        /// </summary>
        protected const string dotXLSX = ".xlsx";

        /// <summary>
        /// .xml
        /// </summary>
        protected const string dotXML = ".xml";

        /// <summary>
        /// .html
        /// </summary>
        protected const string dotHTML = ".html";

        /// <summary>
        /// .htm
        /// </summary>
        protected const string dotHTM = ".htm";

        /// <summary>
        /// .csv
        /// </summary>
        protected const string dotCSV = ".csv";

        /// <summary>
        /// .rtf
        /// </summary>
        protected const string dotRTF = ".rtf";

        /// <summary>
        /// .pdf
        /// </summary>
        protected const string dotPDF = ".pdf";


        /// <summary>
        /// Словарь ед-ц измерения массы в КГ
        /// </summary>
        private static readonly HashSet<string> _kgUnitNames = new HashSet<string>();

        /// <summary>
        /// Словарь ед-ц измерения в ШТ
        /// </summary>
        private static readonly HashSet<string> _pcsUnitNames = new HashSet<string>();


        static BaseOrderFormat()
        {
            _kgUnitNames.Add("килограмм");
            _kgUnitNames.Add("кило");
            _kgUnitNames.Add("kg");
            _kgUnitNames.Add("кг.");

            _pcsUnitNames.Add("шт.");
        }

        private static readonly object _allFormatsMutex = new object();
        private static BaseOrderFormat[] _allFormats = null;

        /// <summary>
        /// Get all formats
        /// </summary>
        public static BaseOrderFormat[] AllFormats
        {
            get
            {
                lock (_allFormatsMutex)
                {
                    if (_allFormats == null)
                    {
                        _allFormats = new BaseOrderFormat[]
                                          {
                                              InputFormats.MariaRA.MariaRaFormat.Instance,
                                              InputFormats.Ashan.AshanFormat.Instance,
                                              InputFormats.Lenta.LentaFormat.Instance,
                                              InputFormats.Holiday.HolidayFormat.Instance,
                                              InputFormats.Holiday.HolidayCsvFormat.Instance,
                                              InputFormats.Excel.ExcelFormat.Instance,
                                              InputFormats.Excel.ExcelNewFormat.Instance,
                                              InputFormats.NewMag.NewMagFormat.Instance,
                                              InputFormats.Art.ArtFormat.Instance,
                                              InputFormats.MosMart.MosMartFormat.Instance,
                                              InputFormats.GlobalMarket.GlobalMarketFormat.Instance,
                                              InputFormats.HyperNovosib.HyperNovosibFormat.Instance,
                                              InputFormats.HyperOmsk.HyperOmskFormat.Instance,
                                              InputFormats.KapitalAlfa.KapitalAlfaFormat.Instance,
                                              InputFormats.Omsk.OmskFormat.Instance,
                                              InputFormats.Excel.Excel2Format.Instance

                                          };
                    }
                }

                return _allFormats;
            }
        }

        protected BaseOrderFormat()
        {
        }

        /// <summary>
        /// Parse
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="getStream"></param>
        /// <returns></returns>
        public abstract BaseOrder Parse(string filePath, Func<Stream> getStream);

        /// <summary>
        /// Parse and translate
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public BaseOrder ParseAndTranslate(string filePath)
        {
            using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                return ParseAndTranslate(filePath, () => stream);
            }
        }

        /// <summary>
        /// Parse and translate
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="getStream"></param>
        /// <returns></returns>
        public BaseOrder ParseAndTranslate(string filePath, Func<Stream> getStream)
        {
            var baseOrder = Parse(filePath, getStream);

            if (baseOrder == null)
            {
                return null;
            }

            foreach (var orderRow in baseOrder.OrderRows)
            {
                //перевод в кг и в шт
                if (!string.IsNullOrEmpty(orderRow.UnitName))
                {
                    string lowUnitName = orderRow.UnitName.ToLowerInvariant();

                    if (_kgUnitNames.Contains(lowUnitName))
                    {
                        orderRow.UnitName = UnitKg;
                    }
                    else
                    {
                        if (_pcsUnitNames.Contains(lowUnitName))
                        {
                            orderRow.UnitName = UnitPcs;
                        }
                    }
                }
            }

            return baseOrder;
        } 

        protected static string[] ReadLines(string filePath)
        {
            return System.IO.File.ReadAllLines(filePath, Encoding.Default);
        }


        /// <summary>
        /// RU Culture
        /// </summary>
        protected static readonly System.Globalization.CultureInfo RuCulture =
            System.Globalization.CultureInfo.GetCultureInfo("ru-RU");

        /// <summary>
        /// кг
        /// </summary>
        public const string UnitKg = "кг";

        /// <summary>
        /// шт
        /// </summary>
        public const string UnitPcs = "шт";

    }
}
